package edu.fit5046.mymonashmate.activity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.mapquest.android.maps.AnnotationView;
import com.mapquest.android.maps.DefaultItemizedOverlay;
import com.mapquest.android.maps.GeoPoint;
import com.mapquest.android.maps.MapView;
import com.mapquest.android.maps.MyLocationOverlay;
import com.mapquest.android.maps.Overlay.OverlayTapListener;
import com.mapquest.android.maps.OverlayItem;

import edu.fit5046.mymonashmate.R;
import edu.fit5046.mymonashmate.utils.DetailInfo;
import edu.fit5046.mymonashmate.utils.HttpUtils;
import edu.fit5046.mymonashmate.utils.SimpleInfo;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;

public class MapActivity extends Activity implements OverlayTapListener,
		OnClickListener {

	private AnnotationView annotation;
	private DefaultItemizedOverlay poiOverlay;
	private MyLocationOverlay myLocationOverlay;
	private MapView map;
	EditText ps0;
	EditText ps1;
	EditText ps2;
	SimpleInfo localInfo;
	DetailInfo localInfoDetail;
	String myinfo;
	List<SimpleInfo> list = new ArrayList<SimpleInfo>();
	private boolean[] checkResult;

	private static final String url = "/entity.mymonashmates";
	private static final String url3 = "/entity.idunits";
	public static final String TAG = "MapQuest";
	private static int touch = 99999;
	private static final int selectNumber = 10;
	private static final GeoPoint caulfieldCampus = new GeoPoint(-37.88164,
			145.05150);

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.layout_map);
		setupMapView();
		setupMyLocation();

		checkResult = new boolean[selectNumber];

		Button btnR = (Button) findViewById(R.id.reset);
		Button btnB = (Button) findViewById(R.id.backward);
		Button btnF = (Button) findViewById(R.id.forward);
		Button btnS = (Button) findViewById(R.id.select_button);

		Button btnC = (Button) findViewById(R.id.changepw_button);
		Button btnM = (Button) findViewById(R.id.myinfo_button);
		Button btnU = (Button) findViewById(R.id.update_button);

		ps0 = (EditText) findViewById(R.id.ps0);
		ps1 = (EditText) findViewById(R.id.ps1);
		ps2 = (EditText) findViewById(R.id.ps2);

		btnR.setOnClickListener(this);
		btnB.setOnClickListener(this);
		btnF.setOnClickListener(this);
		btnS.setOnClickListener(this);
		btnC.setOnClickListener(this);
		btnM.setOnClickListener(this);
		btnU.setOnClickListener(this);
		// use a custom POI marker by referencing the bitmap file directly,
		// using the filename as the resource ID
		Drawable icon_lv0 = getResources().getDrawable(
				R.drawable.location_marker_lv0);
		Drawable icon_lv1 = getResources().getDrawable(
				R.drawable.location_marker_lv1);
		Drawable icon_lv2 = getResources().getDrawable(
				R.drawable.location_marker_lv2);

		poiOverlay = new DefaultItemizedOverlay(icon_lv2);
		try {
			String result = new MyTask().execute(url).get();
			final JSONArray jsarray = new JSONArray(result);
			for (int i = 0; i < jsarray.length(); i++) {
				SimpleInfo ps7 = new SimpleInfo(jsarray.get(i).toString());
				if (ps7.ID == SimpleInfo.localId) {
					localInfo = new SimpleInfo(jsarray.get(i).toString());
					localInfoDetail = new DetailInfo(jsarray.get(i).toString());
				} else {
				}
			}

			String unit = new MyTask().execute(
					url3 + "/getCourseFromID/"
							+ Integer.toString(SimpleInfo.localId)).get();
			JSONArray unitarray = new JSONArray(unit);
			List<String> units = new ArrayList<String>();
			List<Integer> simimates = new ArrayList<Integer>();
			for (int i = 0; i < unitarray.length(); i++) {
				JSONObject a = new JSONObject(unitarray.getJSONObject(i)
						.toString());
				JSONObject b = new JSONObject(a.get("idUnitsPK").toString());
				units.add(b.get("course").toString());
			}
			System.out.println(units.toString());
			for (int i = 0; i < units.size(); i++) {
				String ids = new MyTask().execute(
						url3 + "/getIDFromCourse/" + units.get(i)).get();
				JSONArray idarray = new JSONArray(ids);
				for (int j = 0; j < idarray.length(); j++) {
					JSONObject a = new JSONObject(idarray.getJSONObject(j)
							.toString());
					JSONObject b = new JSONObject(a.get("idUnitsPK").toString());
					simimates.add(b.getInt("sid"));
				}
			}
			Log.i(units.toString(), simimates.toString());
			for (int i = 0; i < jsarray.length(); i++) {
				SimpleInfo ps7 = new SimpleInfo(jsarray.get(i).toString());
				if (ps7.ID == SimpleInfo.localId) {

				} else {
					for (int j = 0; j < simimates.size(); j++) {
						if (ps7.ID == simimates.get(j))
							list.add(ps7);
					}
				}
			}
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		icon_lv0.setBounds(0 - icon_lv0.getIntrinsicWidth() / 2,
				0 - icon_lv0.getIntrinsicHeight(),
				icon_lv0.getIntrinsicWidth() / 2, 0);
		icon_lv1.setBounds(0 - icon_lv1.getIntrinsicWidth() / 2,
				0 - icon_lv1.getIntrinsicHeight(),
				icon_lv1.getIntrinsicWidth() / 2, 0);
		icon_lv2.setBounds(0 - icon_lv2.getIntrinsicWidth() / 2,
				0 - icon_lv2.getIntrinsicHeight(),
				icon_lv2.getIntrinsicWidth() / 2, 0);
		// TODO set similar & not similar
		localInfo.latitude = localInfo.latitude == 0 ? caulfieldCampus
				.getLatitude() : localInfo.latitude;
		localInfo.longitude = localInfo.longitude == 0 ? caulfieldCampus
				.getLongitude() : localInfo.longitude;

		// Caulfield Campus Location by Default
		for (int i = 0; i < list.size(); i++) {
			SimpleInfo p = (SimpleInfo) list.get(i);
			OverlayItem poi1 = new OverlayItem(new GeoPoint(p.latitude,
					p.longitude), p.Name, Integer.toString(p.ID));
			double a = localInfo.latitude;
			double b = localInfo.longitude;
			double c = list.get(i).latitude;
			double d = list.get(i).longitude;
			double e = Distance(a, b, c, d);
			if (e < 0.03) {
				poi1.setMarker(icon_lv0);
				poiOverlay.addItem(poi1);
			} else {
				if (e < 0.10) {
					poi1.setMarker(icon_lv1);
					poiOverlay.addItem(poi1);

				} else {
					poi1.setMarker(icon_lv2);
					poiOverlay.addItem(poi1);
				}
			}
		}

		annotation = new AnnotationView(map);

		// add a tap listener for the POI overlay
		poiOverlay.setTapListener(this);

		map.getOverlays().add(poiOverlay);

	}

	private void getInfo(int ID) {
		Intent intent = new Intent();
		// TODO pass student id to info to invoke all student info
		Bundle bundle = new Bundle();
		bundle.putInt("stuID", ID);
		intent.putExtras(bundle);
		intent.setClass(this, InfoActivity.class);
		startActivity(intent);
	}

	private void updateInfo() {
		Intent intent = new Intent();
		intent.setClass(this, UpdateActivity.class);
		startActivity(intent);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate the menu; this adds items to the action bar if it is present.
		// getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		// int id = item.getItemId();
		// if (id == R.id.action_settings) {
		// return true;
		// }
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onTap(GeoPoint arg0, MapView arg1) {

		// when tapped, show the annotation for the overlayItem
		map.getController().setCenter(arg0);
		int lastTouchedIndex = poiOverlay.getLastFocusedIndex();

		if (lastTouchedIndex > -1) {
			final OverlayItem tapped = poiOverlay.getItem(lastTouchedIndex);
			annotation.showAnnotationView(tapped);
			annotation.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					int get_id;
					get_id = Integer.parseInt(tapped.getSnippet());
					getInfo(get_id);
					Log.i("TAG", Integer.toString(get_id));
				}
			});
		}

	}

	public void onClick(View view) {

		switch (view.getId()) {

		// bottom buttons
		case R.id.reset:
			map.getController().animateTo(
					new GeoPoint(localInfo.latitude, localInfo.longitude));
			map.getController().setZoom(14);
			break;
		case R.id.backward:
			double aB = list.get(touch % list.size()).latitude;
			double bB = list.get(touch % list.size()).longitude;
			GeoPoint geoB = new GeoPoint(aB, bB);
			map.getController().animateTo(geoB);
			map.getController().setZoom(14);
			dialog(touch % list.size());
			touch++;
			break;
		case R.id.forward:
			double aF = list.get(touch % list.size()).latitude;
			double bF = list.get(touch % list.size()).longitude;
			GeoPoint geoF = new GeoPoint(aF, bF);
			map.getController().animateTo(geoF);
			map.getController().setZoom(14);
			dialog(touch % list.size());
			touch--;
			break;
		case R.id.select_button:
			select();
			break;
		// up up up buttons
		case R.id.changepw_button:
			changepw();
			break;
		case R.id.myinfo_button:
			myinfo();
			break;
		case R.id.update_button:
			updateInfo();
			break;
		default:
			break;
		}
	}

	private void changepw() {
		// TODO Auto-generated method stub
		Intent intent = new Intent();
		intent.setClass(this, ChangePWActivity.class);
		startActivity(intent);
	}

	private void setupMapView() {
		this.map = (MapView) findViewById(R.id.map);
		map.setBuiltInZoomControls(true);
	}

	private void setupMyLocation() {
		this.myLocationOverlay = new MyLocationOverlay(this, map);
		myLocationOverlay.enableMyLocation();
		// android.location.Location a = edu.fit5046.mymonashmate.utils.Utils
		// .getLocation(this);
		/*
		 * if (a == null) { AlertDialog.Builder builder = new Builder(this);
		 * builder.setMessage("Using Caulfield Campus by default");
		 * builder.setTitle("Please Turn on Location Service");
		 * builder.setPositiveButton("Confirm", new
		 * DialogInterface.OnClickListener() { public void
		 * onClick(DialogInterface dialog, int which) { dialog.dismiss(); } });
		 * 
		 * builder.create().show(); Log.i("TAG", "no location service running");
		 * map.getController().setCenter(new GeoPoint(-37.88164, 145.05150));
		 * map.getController().setZoom(14);
		 * 
		 * } else
		 */

		myLocationOverlay.runOnFirstFix(new Runnable() {
			@Override
			public void run() {
				GeoPoint currentLocation = myLocationOverlay.getMyLocation();
				String getLatitude = Double.toString(currentLocation
						.getLatitude());
				String getLongitude = Double.toString(currentLocation
						.getLongitude());
				String command = url + "/get/"
						+ Integer.toString(SimpleInfo.localId);
				String result;
				try {
					result = new MyTask().execute(command).get();
					JSONObject js = new JSONObject(result);
					js.put("latitude", currentLocation.getLatitude());
					js.put("longitude", currentLocation.getLongitude());
					result = new MyTask().execute(url + "/edit", js.toString())
							.get();
					Log.i(TAG, result);
				} catch (InterruptedException | ExecutionException
						| JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				Log.i("TAG", getLatitude + " " + getLongitude);
				map.getController().animateTo(currentLocation);
				map.getController().setZoom(14);
				map.getOverlays().add(myLocationOverlay);
				// myLocationOverlay.setFollowing(true);
			}
		});
	}

	private void myinfo() {
		getInfo(SimpleInfo.localId);
	}

	@SuppressLint("NewApi")
	private void select() {
		final List<Integer> myIntest = new ArrayList<Integer>();
		final String[] items = { "Natinality", "Fistr Language",
				"Second Language", "Surburb", "Favourite Food",
				"Favourite Movie", "Favourite Unit",
				"Favourite Program Language", "Current Job", "Previous Job" };

		new AlertDialog.Builder(MapActivity.this)
				.setTitle("Select what you want to match :)")
				.setMultiChoiceItems(items, checkResult,
						new DialogInterface.OnMultiChoiceClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which, boolean isChecked) {

								checkResult[which] = isChecked;

							}
						})
				.setPositiveButton("Comfirm",
						new DialogInterface.OnClickListener() {
							public void onClick(
									DialogInterface dialoginterface, int i) {
								for (int count = 0; count < selectNumber; count++) {
									if (checkResult[count]) {
										myIntest.add(count);
									}
								}

								try {
									match(myIntest);
								} catch (InterruptedException
										| ExecutionException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}

								System.out.println(myIntest.toString());
								Toast.makeText(getApplicationContext(),
										myIntest.size() + "item(s) selected",
										Toast.LENGTH_LONG).show();
								Toast.makeText(getApplicationContext(),
										"Press B/F to see matching score",
										Toast.LENGTH_LONG).show();
								dialoginterface.dismiss();
							}
						}).show();

	}

	@SuppressLint({ "NewApi", "UseSparseArrays" })
	public void match(List<Integer> myIntest) throws InterruptedException,
			ExecutionException {
		String[] target = { "Ni1", "Ni1", "Ni1", "Ni1", "Ni1", "Ni1", "Ni1",
				"Ni1", "Ni1", "Ni1" };
		String js = "";
		/* myinterst<Integer> */
		for (int i = 0; i < myIntest.size(); i++) {
			switch (myIntest.get(i).intValue()) {
			case 0:
				target[0] = localInfoDetail.nationNanity;
				break;
			case 1:
				target[1] = localInfoDetail.firstLanguage;
				break;
			case 2:
				target[2] = localInfoDetail.secondLanguage;
				break;
			case 3:
				target[3] = localInfoDetail.address;
				break;
			case 4:
				target[4] = localInfoDetail.favouriteFood;
				break;
			case 5:
				target[5] = localInfoDetail.favouriteMovie;
				break;
			case 6:
				target[6] = localInfoDetail.favouriteUnit;
				break;
			case 7:
				target[7] = localInfoDetail.favouriteProgremLanguage;
				break;
			case 8:
				target[8] = localInfoDetail.currentJob;
				break;
			case 9:
				target[9] = localInfoDetail.previousJob;
				break;
			}

			if (target[myIntest.get(i).intValue()].isEmpty())
				target[myIntest.get(i).intValue()] = "Ni1";

			target[myIntest.get(i).intValue()] = target[myIntest.get(i)
					.intValue()].replace("1Nvi5IblE", "");
		}
		js = js + "/" + "Ni1" + "/" + "Ni1";
		for (int i = 0; i < selectNumber; i++) {
			js += "/";
			js += target[i];
		}
		js = js.replace(" ", "%20");
		String scoreList = new MyTask().execute(url + "/matchingScore" + js)
				.get();

		Log.i("From Server", scoreList);

		scoreList = scoreList.replace("{", "");
		scoreList = scoreList.replace("}", "");
		scoreList = scoreList.replace(",", "");

		String tmpSC[] = scoreList.split(" ");
		HashMap<Integer, Integer> scoreMap = new HashMap<Integer, Integer>();
		for (int i = 0; i < tmpSC.length; i++) {
			String tmp[] = tmpSC[i].split("=");
			scoreMap.put(Integer.parseInt(tmp[0]), Integer.parseInt(tmp[1]));
		}

		Log.i("From Local Map", scoreMap.toString());

		for (int i = 0; i < list.size(); i++) {
			list.get(i).matching_score = 0;
			for (int j = 0; j < scoreMap.size(); j++) {
				if (scoreMap.containsKey(list.get(i).ID)) {
					list.get(i).matching_score = scoreMap.get(list.get(i).ID);
				}
			}
			System.out.println(list.get(i).ID + "&"
					+ list.get(i).matching_score);
		}
	}

	public static double Distance(double mGeo0, double mGeo1, double tGeo0,
			double tGeo1) {
		return Math.sqrt((mGeo0 - tGeo0) * (mGeo0 - tGeo0) + (mGeo1 - tGeo1)
				* (mGeo1 - tGeo1));
	}

	void dialog(int f) {
		if (list.get(f).matching_score == 0) {
			new AlertDialog.Builder(MapActivity.this)
					.setTitle(
							"Your have nothing in common with "
									+ list.get(f).Name)
					.setPositiveButton("Comfirm",
							new DialogInterface.OnClickListener() {
								public void onClick(
										DialogInterface dialoginterface, int i) {
									dialoginterface.dismiss();
								}
							}).show();
		} else {
			if (list.get(f).matching_score > 5) {
				new AlertDialog.Builder(MapActivity.this)
						.setTitle(
								list.get(f).Name
										+ " is your potential friend cause your score is: "
										+ Integer.toString(list.get(f).matching_score))
						.setPositiveButton("Comfirm",
								new DialogInterface.OnClickListener() {
									public void onClick(
											DialogInterface dialoginterface,
											int i) {
										dialoginterface.dismiss();
									}
								}).show();
			} else {
				if (list.get(f).matching_score > 3) {
					new AlertDialog.Builder(MapActivity.this)
							.setTitle(
									list.get(f).Name
											+ " has "
											+ Integer.toString(list.get(f).matching_score)
											+ " things similar with you")
							.setPositiveButton("Comfirm",
									new DialogInterface.OnClickListener() {
										public void onClick(
												DialogInterface dialoginterface,
												int i) {
											dialoginterface.dismiss();
										}
									}).show();
				} else {
					new AlertDialog.Builder(MapActivity.this)
							.setTitle(
									"Your Matching Score with "
											+ list.get(f).Name
											+ " is "
											+ Integer.toString(list.get(f).matching_score))
							.setPositiveButton("Comfirm",
									new DialogInterface.OnClickListener() {
										public void onClick(
												DialogInterface dialoginterface,
												int i) {
											dialoginterface.dismiss();
										}
									}).show();
				}
			}
		}

	}

	private class MyTask extends AsyncTask<String, String, String> {
		@Override
		protected String doInBackground(String... prm) {
			// TODO Auto-generated method stub
			if (prm.length == 1)
				return HttpUtils.Get(prm[0]);
			if (prm.length == 2)
				return HttpUtils.Edit(prm[0], prm[1]);
			else
				return null;
		}

		protected void onPostExecute(String result) {
			super.onPostExecute(result);
		}

	}

}
